/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package injections;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @author Tom
 */
public final class SingletonHolder {

    private static final Logger LOGGER = LoggerFactory.getLogger(SingletonHolder.class);
    private static final List<SingletonHolder> instances = new CopyOnWriteArrayList<>();
    private final Map<String, Object> map = new ConcurrentHashMap<>();

    static {
        // shutdown hook
        LOGGER.info("Setting up SingletonHolder, registering shutdown hook");
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                for (SingletonHolder holder : instances) {
                    LOGGER.info("Running shutdown hook");
                    List<AutoCloseable> toClose = new ArrayList<>();
                    for (Map.Entry<String, Object> e : holder.map.entrySet()) {
                        Object o = e.getValue();
                        if (o instanceof AutoCloseable) {
                            toClose.add((AutoCloseable) o);
                        }
                    }
                    for (AutoCloseable c : toClose) {
                        LOGGER.info("Closing " + c + " - instance of " + c.getClass().getName());
                        try {
                            c.close();
                        } catch (Exception e1) {
                            LOGGER.warn("Error while closing " + c);
                        }
                    }
                }
            }
        });
    }

    private SingletonHolder() {
        // nothing
    }

    public static SingletonHolder createInstance() {
        SingletonHolder ins = new SingletonHolder();
        SingletonHolder.instances.add(ins);
        return ins;
    }

    public Object getSingleton(String name) {
        Object obj = map.get(name);
        return obj;
    }

    public void putSingleton(String name, Object obj) {
        map.put(name, obj);
    }
}
